using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;


namespace xna_game_engine.source
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class Old_warrior : Entity
    {
        private Dictionary<EQUIPMENT_SLOTS, BaseItem> mEquippedItems;

        // functions
        public Old_warrior(string name) : base(name)
        {
            mAnim = new CAnimation(6, 32, 32, 2);
            mDirection = Vector2.Zero;
            mIsMoving = false;
            mPosition = new Vector2(0.0f, 0.0f);
            mVelocity = new Vector2(0.0f, 0.0f);
            mHealthTickRegen = 2.0f;
            mManaTickRegen = 20.0f;
            mHealthTickTimer = new TongaTimer(2);
            mManaTickTimer = new TongaTimer(0.5);
            mHealthBar = new StatusBar(new Vector2(1.0f, 1.0f), Color.Red, Color.Green);
            mManaBar = new StatusBar(new Vector2(1.0f, 0.5f), Color.CadetBlue, Color.DarkBlue);
            mLevelTable = new Dictionary<int, int>();
            mEquippedItems = new Dictionary<EQUIPMENT_SLOTS, BaseItem>();
        }

        // Parental overrides
        public override void Initialize()
        {
            // Setup our stats...
            mStats["Strength"] = 15;
            mStats["Intellect"] = 10;
            mStats["Agility"] = 7;
            mStats["Stamina"] = 10  ;
            mStats["Vim"] = 5;

            // Calc our stats
            CalcStats();

            // Teach us some spells
            LearnSpell(SpellSystem.Heal1);
            LearnSpell(SpellSystem.Fireball1);
            LearnSpell(SpellSystem.Mend1);
            LearnSpell(SpellSystem.Poison1);
            LearnSpell(SpellSystem.ChainLit1);

            // Level xp table
            mLevelTable.Add(1, 0);
            mLevelTable.Add(2, 100);
            mLevelTable.Add(3, 250);
            mLevelTable.Add(4, 450);
            mLevelTable.Add(5, 700);
            mLevelTable.Add(6, 1000);

            mEquippedItems[EQUIPMENT_SLOTS.CHEST] = new BaseItem("Empty");
            mEquippedItems[EQUIPMENT_SLOTS.FEET] = new BaseItem("Empty");
            mEquippedItems[EQUIPMENT_SLOTS.HEAD] = new BaseItem("Empty");
            mEquippedItems[EQUIPMENT_SLOTS.LEFT_HAND] = new BaseItem("Empty");
            mEquippedItems[EQUIPMENT_SLOTS.LEGS] = new BaseItem("Empty");
            mEquippedItems[EQUIPMENT_SLOTS.RIGHT_HAND] = new BaseItem("Empty");
            mEquippedItems[EQUIPMENT_SLOTS.SHOULDERS] = new BaseItem("Empty");
        }

        public override void LoadContent(ContentManager cm)
        {
            mTexture = cm.Load<Texture2D>("sprites\\Old_warrior");
            mAnimTexture = cm.Load<Texture2D>("sprites\\Old_warrior_anim");
            mHealthBar.LoadContent();
            mManaBar.LoadContent();
            mTextFont = cm.Load<SpriteFont>("fonts\\test_font");

            // Setup bounding box
            mBoundingBox.Max = new Vector3(mPosition.X + mTexture.Width, mPosition.Y + mTexture.Height, 0);
            mBoundingBox.Min = new Vector3(mPosition.X, mPosition.Y, 0);

            mAnim.Update(new GameTime(), Vector2.Zero);
        }

        public override void Draw()
        {
            if (!mIsDead)
            {
                GameSystems.Graphics.DrawAnimation(mAnim, AnimTexture, mPosition, Color.White);
                mHealthBar.Draw(new Vector2(0.0f, 25.0f));
                mManaBar.Draw(new Vector2(0.0f, 55.0f));
                GameSystems.Graphics.DrawText(mName, new Vector2(10.0f, 3.0f), Color.White);
                GameSystems.Graphics.DrawText(Math.Floor(mCurHP) + " / " + Math.Floor(mMaxHP), new Vector2(85.0f, 28.0f), Color.White);
                GameSystems.Graphics.DrawText(Math.Floor(mCurMP) + " / " + Math.Floor(mMaxMP), new Vector2(85.0f, 52.0f), Color.White);
                //GameSystems.Graphics.DrawText("Strength: " + mStats["Strength"], new Vector2(10.0f, 30.0f), Color.White);
                //GameSystems.Graphics.DrawText("Intellect : " + mStats["Intellect"], new Vector2(10.0f, 50.0f), Color.White);
                //GameSystems.Graphics.DrawText("Agility    : " + mStats["Agility"], new Vector2(10.0f, 70.0f), Color.White);
                //GameSystems.Graphics.DrawText("Stamina : " + mStats["Stamina"], new Vector2(10.0f, 90.0f), Color.White);
                //GameSystems.Graphics.DrawText("Vim        : " + mStats["Vim"], new Vector2(10.0f, 110.0f), Color.White);
                GameSystems.Graphics.DrawText("Xp        : " + mCurXP, new Vector2(10.0f, 70.0f), Color.White);
                GameSystems.Graphics.DrawText("Level     : " + mCurLevel, new Vector2(10.0f, 90.0f), Color.White);
                GameSystems.Graphics.DrawText("Gold     : " + mCurGold, new Vector2(10.0f, 110.0f), Color.White);

                GameSystems.Graphics.DrawText("-- Active spells -- ", new Vector2(10.0f, 130.0f), Color.White);
                for (int i = 0; i < mActiveSpells.Count; i++)
                {
                    if (mActiveSpells[i].IsActive())
                    {
                        GameSystems.Graphics.DrawText(mActiveSpells[i].GetName(), new Vector2(10.0f, 150.0f + (i * 20)), Color.White);
                    }
                }
            }
        }

        public override void EquipItem(BaseItem item, EQUIPMENT_SLOTS slot)
        {
            // Check it item can be equipped in chosen slot
            if (item.Slots.Contains(slot))
            {
                if (mEquippedItems[slot].Name != "Empty")
                {
                    // This slot is occupied, remove item first
                    ApplyItemStats(item, true);
                }
                else
                {
                    // Otherwise just apply stats
                    ApplyItemStats(item, false);
                }

                mEquippedItems[slot] = item;
                
                CalcStats();
                GameGlobals.MessageBox.AddEntry(mName + " has equipped a " + item.Name + "!");

            }
        }

        // <summary>
        /// Modify the entity's health.
        /// </summary>
        /// <param name="amt">positive to heal, negative to damage</param>
        public override void ModHealth(float amt, bool isRegenTick)
        {
            if (amt > 0 && !isRegenTick)
            {
                GameGlobals.CombatText.Trigger(this, amt.ToString(), Color.Green);
                GameGlobals.MessageBox.AddEntry(mName + " is healed for " + amt + " hp!");
            }
            else if (amt < 0)
            {
                GameGlobals.CombatText.Trigger(this, amt.ToString(), Color.Red);
                GameGlobals.MessageBox.AddEntry(mName + " takes " + Math.Abs(amt) + " points of damage!");
            }

            mCurHP += amt;
            if (mCurHP < 0)
            {
                mCurHP = 0;
                GameGlobals.MessageBox.AddEntry(mName + " has died.");
            }
            else if (mCurHP > mMaxHP)
            {
                mCurHP = mMaxHP;
            }
        }

        public override void LevelUp(int timesToLevel)
        {
            for (int i = 0; i < timesToLevel; i++)
            {
                mCurHP = mMaxHP = mMaxHP * 1.1f;
                mCurMP = mMaxMP = mMaxMP * 1.1f;
                mCurLevel++;
            }
            //GameSystems.Particles.BasicTrigger(mPosition + new Vector2(16, 16), Color.White);
            GameSystems.Audio.PlaySoundCue("level_up");
        }

        // Other functions
        public void Update(GameTime gt)
        {
            // Recalc our stats
            //mMaxHP = 12 * mStats["Stamina"];

            // BaseUpdate takes care of health, so hand out mana here
            mManaBar.Update(gt, (mCurMP / mMaxMP));
            if (mIsMoving)
            {
                mAnim.Update(gt, mDirection);
                mPosition += mVelocity * 2.5f; //  2.5f should be the speed, hard coding is BAD!
            }
            mIsMoving = false;
            BaseUpdate(gt);
        }

        public void CalcStats()
        {
            // Calc our stats
            mMaxHP = mCurHP = 10 * mStats["Stamina"];
            mMaxMP = mCurMP = 10 * mStats["Intellect"];
        }

        private void ApplyItemStats(BaseItem item, bool removing)
        {
            if (true == removing)
            {
                // Do stuff based on item being equipped
                foreach (KeyValuePair<string, int> kvp in item.StatMods)
                {
                    string statName = kvp.Key;
                    int statValue = kvp.Value;

                    mStats[statName] -= statValue;
                }

                foreach (KeyValuePair<string, int> kvp in item.Mods)
                {
                    string modName = kvp.Key;
                    int modValue = kvp.Value;

                    switch (modName)
                    {
                        case "Health":
                            {
                                mCurHP -= modValue;
                                mMaxHP -= modValue;
                            }
                            break;
                        case "Mana":
                            {
                                // TODO: add mana
                            }
                            break;
                        case "Attack":
                            {
                                // TODO: Add attack
                            }
                            break;
                        case "Defense":
                            {
                                // TODO: Add defense
                            }
                            break;
                        case "HealthRegen":
                            {
                                mHealthTickRegen -= modValue;
                            }
                            break;
                        case "ManaRegen":
                            {
                                mManaTickRegen -= modValue;
                            }
                            break;
                        default:
                            break;
                    }
                }
            }
            // Add item
            foreach (KeyValuePair<string, int> kvp in item.StatMods)
            {
                string statName = kvp.Key;
                int statValue = kvp.Value;

                mStats[statName] += statValue;
            }

            foreach (KeyValuePair<string, int> kvp in item.Mods)
            {
                string modName = kvp.Key;
                int modValue = kvp.Value;

                switch (modName)
                {
                    case "Health":
                        {
                            mCurHP += modValue;
                            mMaxHP += modValue;
                        }
                        break;
                    case "Mana":
                        {
                            // TODO: add mana
                        }
                        break;
                    case "Attack":
                        {
                            // TODO: Add attack
                        }
                        break;
                    case "Defense":
                        {
                            // TODO: Add defense
                        }
                        break;
                    case "HealthRegen":
                        {
                            mHealthTickRegen += modValue;
                        }
                        break;
                    case "ManaRegen":
                        {
                            mManaTickRegen += modValue;
                        }
                        break;
                    default:
                        break;
                }
            }
        }

        #region Properties
            
        #endregion
    }
}